Persistent Operating System Support for Java

نویسندگان

  • Alan Dearle
  • David Hulse
  • Alex Farkas
چکیده

Over the last 15 years a number of persistent language systems have been produced whose implementation relies on the persistence mechanisms provided by an underlying operating system. We have produced an operating system called Grasshopper expressly designed to support orthogonally persistent systems. In this paper we demonstrate how the mechanisms provided by Grasshopper may be used to implement a persistent version of the language Java. 1 . Introduction Over the last ten to fifteen years a number of persistent language systems have been developed. Some of these were designed to be persistent from the outset [3, 19], others are persistent versions of ordinary programming languages e.g. [21]. What these language systems have in common is that they have been implemented as separate language systems above a nonpersistent operating system. It is our belief that, although persistence can be implemented by a programming language run time system, the persistence of data should be provided by the operating system. Implementing persistence at the programming language level suffers from two major drawbacks. First, the host operating system was not designed to support persistence; therefore the operating system interface does not usually provide abstractions sympathetic to a persistent language implementation. The consequence of this is that the language designer is usually forced to implement a persistent abstract machine above the operating system abstractions, resulting in a loss of efficiency. A similar problem is reported by the designers of database systems [22]. The second problem with this approach is that every persistent language implements its own persistent abstract machine duplicating much of the functionality found inside the operating system and other language implementations. Often these different implementations are entirely incompatible with each other, prohibiting interactions between programs written in different languages. This would appear to be a retrograde step compared to the mixed language environments supported by conventional systems. The implementation of the persistence abstraction by the operating system avoids these problems. We believe that such an approach to operating system design could be as revolutionary as virtual memory in terms of the advantages for user-level applications. We have constructed the Grasshopper operating system in order to investigate these assertions. In this paper we show how one non-persistent language, Java [14] may be made persistent under Grasshopper. In addition to this language system, our current Grasshopper prototype also supports persistent assembler, C, C++ and Napier88. When considering the persistent storage requirements of Java we must consider six different aspects: 1. the persistent storage of Java source code, 2. the storage of Java executable code in class files, 3. Java object repositories, 4. binding to persistent objects, 5. the state of active Java threads, and 6. the recoverability of state following a failure. In most persistent Java implementations, the first two categories would be handled by the (non persistent) operating system, the latter by some language layer. In Grasshopper, support for all six categories is provided by the operating system. The remainder of the paper discusses these six aspects. 2 . Persistent storage of source and class files The persistent storage of source and class files presents three requirements: 1. some persistent storage must be provided to store the data, 2. some naming mechanisms must be provided for finding the files, and 3. some protection mechanism must be provided to prevent unauthorised access to files and to prevent unauthorised modification. In Grasshopper the first of these is satisfied by a single abstraction known as a container [11]. Containers are the only storage abstraction provided by Grasshopper. They are persistent entities which fulfil the roles traditionally served by both address spaces and files. In most operating systems, the notion of a virtual address space is associated with an ephemeral entity, a process, which accesses data within that address space. In contrast, containers and processes (called loci in Grasshopper) are orthogonal concepts. A Grasshopper system consists of a number of containers which may have loci executing within them. Loci are migratory in nature and may move from container to container by invoking them. Each container that supports invocation has a well defined interface specified in IDL [20]. It is convenient, natural and efficient to implement Java source and class files using Grasshopper containers. However, some naming scheme must be provided to enable files to be logically organised. For this purpose, Grasshopper provides attributed namespaces. Namespaces implement a mapping from names to Grasshopper capabilities [10]. In Grasshopper every object known to the operating system is represented at user level by one or more capabilities which consist of a reference to a Grasshopper entity and access rights associated with it. The capability system therefore implements both low level naming and protection. The capability mechanism is deliberately simple and low-level for reasons of efficiency and flexibility. Namespaces are themselves implemented as containers containing both code and data. Namespaces present an abstract table interface similar to that supported by the PS-algol tables [1] package. However, the mappings may have string, integer, boolean and capability attributes associated with them. Attributes are useful for representing modification dates, type information, ownership etc. Typically, namespaces are arranged in hierarchies as shown in Figure 1. Some protection mechanism must be provided to prevent unauthorised access to data and to prevent unauthorised modification. In Grasshopper the first of these requirements is provided by the capability system. No Grasshopper entity can be accessed without the presentation of a valid capability. Although capabilities are stored in namespaces, not all namespaces are publicly accessible. Each user has his or her own namespace from which other namespaces are reachable. Users may choose to make their namespaces known in a secure manner using functions provided by the login service, however, this is beyond the scope of this paper. Access to a container does not give unrestricted access to the data it contains as is the case with Unix files. The capability system may prevent invocation or mapping (see below) and the kernel supports the usual page level protection mechanisms preventing reading or writing of data stored in containers. The ability to change page protections is itself protected using the capability system thereby preventing unauthorised users from performing illegal operations. Figure 1: Grasshopper container organisation 3 . Java object repositories The persistent store against which Java programs operate (the object repository) may also be provided by a Grasshopper container. Containers may be organised in any manner required by the persistent application system using them. In the case of Java, the object repository is required to contain: 1. Java class files, 2. the Java run-time system (the interpreter), 3. stacks for threads, 4. shared libraries, and, 5. at least one heap containing Java objects. Grasshopper enables this via the provision of container mappings. The purpose of container mapping is to allow data to be shared between containers. This is achieved by allowing data in a region of one container to be viewed within a region of another container. Mappings may be global, or visible to only a single locus. Unlike other memory object mechanisms, containers may be arbitrarily (possibly recursively) composed using mapping which provides considerably enhanced flexibility and performance [16]. Another difference between mappings in Grasshopper and other systems is that mappings in Grasshopper are persistent and remain in force until the data is unmapped. Using the container mapping mechanism, the Java run time system and shared libraries may be mapped into one or more object repositories; this is shown in Figure 2. This allows code to be shared in both virtual memory and on disk [16]. At this point it is worth noting the C computations implementing the Java run time system (including global variables) are automatically persistent due to the fact that Grasshopper containers are truly orthogonally persistent address spaces. Note that the mapping mechanism is used because it is natural at the logical level, not as a mechanism with which to implement the recoverability of the persistent store [6]. Figure 2: Mappings in the Java object repository As described above, mappings may be established globally or on a per locus basis. The latter provides a mechanism by which each thread (locus) may have its own stack and heap space which is invisible to all other loci in the system. Indeed, the stacks and heaps may be located at the same address within the container in which they are executing. This considerably simplifies memory management and adds a degree of inter-thread protection unavailable in most systems. However, this approach was not employed in the Java system due to the requirement of the garbage collector to view thread stacks. The technique of giving each concurrent persistent process its own local heap was used in the CASPER system [23]. In this system it was found that the use of copy-out techniques borrowed from generational garbage collection considerably reduced the work of garbage collecting the global heap. It is expected that similar results will be found in the case of Java whose architecture is very similar to that of Napier88 [8]. However, at the time of writing, this technique has not been implemented in the prototype and therefore further results are not currently available. 4 . Binding In all persistent systems, some mechanism must be provided to permit objects to make bindings to other objects in the persistent store. In Grasshopper, since each container provides an orthogonally persistent address space, any locus can generate an arbitrary address in the container in which it is executing and access the persistent data stored there. Such a mechanism is not particularly useful in a language such as Java which does not support pointers. However, it can be used to implement arbitrary intra-container naming schemes such as those provided by tables in PS-algol [1], environments in Napier88 [9] and the pJavaStore functionality suggested by Atkinson for Java [4]. Furthermore, the style of persistence provided by containers makes this easy to implement in Java. Since all class files loaded into a container automatically become persistent and the heap data is also persistent, class variables automatically become persistent. Figure 3 shows a simple example of the use of this form of persistence. Whenever this Java program is executed it will print out the value of the persistent class variable x and increment its value. import java.lang.System; public class classvar { static int x = 0; public static void main(String argv[]) { System.out.print("Running classvar value is: " + x + "\n"); x = x + 1; System.exit(0);

برای دانلود رایگان متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

منابع مشابه

Operating System support for Java

Over the last 15 years a number of persistent language systems have been produced whose implementation relies on the persistence mechanisms provided by an underlying operating system. We have produced an operating system called Grasshopper expressly designed to support orthogonally persistent systems. In this paper we demonstrate how the mechanisms provided by Grasshopper may be used to impleme...

متن کامل

Type Evolution and Version Management in a Persistent Distributed Operating System

Todays commercial Operating Systems (OS) use message passing communication facilities such as Corba, Remote Procedure Calls, and TCP/IP. Distributed Shared Memory (DSM) is an alternative mainly used for scientific computing and specific parallel algorithms. We are currently developing a general purpose PC Operating System using the DSM paradigm as communication media. A new memory consistency m...

متن کامل

Linking and Loading in a Persistent Dsm Operating System

Our native Java compiler directly generates runtime structures in a persistent Distributed Shared Memory (DSM). The compiler has been used to build a general purpose PC Operating System (OS) on top of a persistent DSM memory. The persistent DSM operating environment lends itself naturally to an integration of symbol tables, class descriptors and naming during Java program compilation and execut...

متن کامل

Lumberjack: A Log-Structured Persistent Object Store

Lumberjack is a log-structured persistent object store intended for use with conventional operating systems such as Unix. The design draws together facets of previous work, in particular, the CPOMS object store used to support PS-algol, and the page-based log-structured store used in the Grasshopper persistent operating system. Lumberjack exhibits a novel store design that provides a number of ...

متن کامل

Implementation Aspects of a Persistent DSM Operating System in Java

The Java trademark encompasses the Java Virtual Machine (JVM), the Java language itself, and a large continuously growing class library. Beyond the development of applets in the context of the World Wide Web, more and more people use Java for large scaled standalone applications. This user group points out the performance disadvantage of the Java environment in comparison to sophisticated C/C++...

متن کامل

ذخیره در منابع من


  با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید

عنوان ژورنال:

دوره   شماره 

صفحات  -

تاریخ انتشار 1996